package com.myhome.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.myhome.domain.Account;
import com.myhome.domain.CashRecharge;
import com.myhome.domain.Config;
import com.myhome.dto.BankDto;
import com.myhome.dto.UserDto;
import com.myhome.feign.UserBankInfo;
import com.myhome.feign.UserFeign;
import com.myhome.model.SellCashRechargeParam;
import com.myhome.service.AccountService;
import com.myhome.service.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.myhome.domain.CashWithdrawals;
import com.myhome.mapper.CashWithdrawalsMapper;
import com.myhome.service.CashWithdrawalsService;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

/**
*@Author QYiXin 
* @Date 2021 10 20 09 37
**/
@Service
public class CashWithdrawalsServiceImpl extends ServiceImpl<CashWithdrawalsMapper, CashWithdrawals> implements CashWithdrawalsService{
    @Autowired
    UserFeign userFeign;
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    ConfigService configService;
    @Autowired
    UserBankInfo userBankInfo;
    @Autowired
    AccountService accountService;

    @Override
    public Page<CashWithdrawals> findPages(Long userId, String userName, String mobile, Byte status, String numMin, String numMax, String startTime, String endTime, Page<CashWithdrawals> page) {
        Map<Long, UserDto> userDtoMap = null;
        LambdaQueryWrapper<CashWithdrawals> lambdaQuery = new LambdaQueryWrapper<>();
        if (userId != null | mobile != null || userName != null) {
            userDtoMap = userFeign.getMapUserDto(Arrays.asList(userId), userName, mobile);
            if (ObjectUtils.isEmpty(userDtoMap)) {
                return page;
            }
            lambdaQuery.in(!ObjectUtils.isEmpty(userDtoMap), CashWithdrawals::getUserId, userDtoMap.keySet());
        }
        lambdaQuery.eq(status!=null,CashWithdrawals::getStatus, status)
                .between((!StringUtils.isEmpty(startTime) && !StringUtils.isEmpty(endTime)), CashWithdrawals::getCreated, startTime, endTime + " 23:59:59")
                .between((!StringUtils.isEmpty(numMax) && !StringUtils.isEmpty(numMin)), CashWithdrawals::getNum, new BigDecimal(numMin == null ? "0" : numMin), new BigDecimal(numMax == null ? "0" : numMax));
        Page<CashWithdrawals> result = this.page(page, lambdaQuery);
        if (result != null) {
            List<CashWithdrawals> records = result.getRecords();
            if(userDtoMap==null){ // 说明前面没有使用用户的信息查询用户
                List<Long> userIds = records.stream().map(cashRecharge -> cashRecharge.getUserId()).collect(Collectors.toList());
                if (!CollectionUtil.isEmpty(userIds)) {
                    userDtoMap =  userFeign.getMapUserDto(userIds,null,null) ;
                }
            }
            for (CashWithdrawals record : records) {
                if (userDtoMap != null) {
                    UserDto userDto = userDtoMap.get(record.getUserId());
                    if (userDto != null) {
                        record.setUsername(userDto.getUsername());
                        record.setRealName(userDto.getRealName());
                    }
                }
            }
        }
        return result;
    }

    @Override
    public Page<CashWithdrawals> findCashWithdrawals(Page<CashWithdrawals> page, Long userId, Byte status) {
        return page(page,new LambdaQueryWrapper<CashWithdrawals>()
                .eq(CashWithdrawals::getUserId,userId)
                .eq(status!=null,CashWithdrawals::getStatus,status));
    }

    @Override
    public Boolean sellCashRecharge(Long userId, SellCashRechargeParam sellCashRechargeParam) {
        Map<Long, UserDto> userDtoMap = userFeign.getMapUserDto(Arrays.asList(userId), null, null);
        if (CollectionUtil.isEmpty(userDtoMap)) {
            throw new IllegalArgumentException("不存在该用户的信息");
        }
        UserDto userDto = userDtoMap.get(userId);
        //卖出金额校验
        checkSellMum(sellCashRechargeParam.getMum());
        //验证码校验
        checkValidateCode(userDto.getMobile(),sellCashRechargeParam.getValidateCode());
        //支付密码的校验
        checkPayPassword(userDto.getPaypassword(),sellCashRechargeParam.getPayPassword());
        //远程调用
        BankDto userBankInfo = this.userBankInfo.getUserBankInfo(userId);
        Account account = accountService.getUserAccountInfoByUserId(userId,sellCashRechargeParam.getCoinId());
        if (account == null) {
            throw new IllegalArgumentException("不存在该用户账户");
        }
        Config drawRateConfig = configService.getConfigByCode("WITHDRAW_POUNDAGE_RATE");
        Config minFeeConfig = configService.getConfigByCode("WITHDRAW_MIN_POUNDAGE");
        BigDecimal countMinFee = new BigDecimal(drawRateConfig.getValue()).multiply(sellCashRechargeParam.getMum()).setScale(2, RoundingMode.HALF_UP);
        BigDecimal resultFee = countMinFee.compareTo(new BigDecimal(minFeeConfig.getValue())) > 0 ? countMinFee : new BigDecimal(minFeeConfig.getValue());
        //提现记录的创建
        CashWithdrawals cashWithdrawals = new CashWithdrawals();
        cashWithdrawals.setRealName(userDto.getRealName());
        cashWithdrawals.setUsername(userDto.getRealName());
        cashWithdrawals.setAccountId(account.getId());
        cashWithdrawals.setBank(userBankInfo.getBank());
        cashWithdrawals.setBankCard(userBankInfo.getBankCard());
        cashWithdrawals.setBankAddr(userBankInfo.getBankAddr());
        cashWithdrawals.setBankCity(userBankInfo.getBankCity());
        cashWithdrawals.setBankProv(userBankInfo.getBankProv());
        cashWithdrawals.setCreated(new Date());
        cashWithdrawals.setFee(resultFee);
        cashWithdrawals.setCoinId(sellCashRechargeParam.getCoinId());
        BigDecimal resultMum = sellCashRechargeParam.getMum().subtract(resultFee);
        cashWithdrawals.setMum(resultMum);
        cashWithdrawals.setNum(sellCashRechargeParam.getNum());
        cashWithdrawals.setStep((byte) 0);
        cashWithdrawals.setStatus((byte)1);
        cashWithdrawals.setTruename(userBankInfo.getRealName());
        cashWithdrawals.setUserId(userId);
        Boolean isSell = this.save(cashWithdrawals);
        if (isSell) {
            account.setBalanceAmount(account.getBalanceAmount().subtract(sellCashRechargeParam.getNum()));
            boolean isUpdate = accountService.updateById(account);
            if (!isUpdate) {
                throw new IllegalArgumentException("提现失败");
            }
            return true;
        }
        return false;
    }
    private void checkSellMum(BigDecimal mum) {
        Config minConfig = configService.getConfigByCode("WITHDRAW_MIN_AMOUNT");
        Config maxConfig = configService.getConfigByCode("WITHDRAW_MAX_AMOUNT");
        if (mum.compareTo(new BigDecimal(minConfig.getValue())) < 0) {
            throw new IllegalArgumentException("提现金额过小");
        }
        if (mum.compareTo(new BigDecimal(maxConfig.getValue())) >0) {
            throw new IllegalArgumentException("提现金额过大");
        }
    }

    private void checkValidateCode(String mobile,String validateCode) {
        String code = (String) redisTemplate.opsForValue().get("SMS" + mobile + "CODE");
        if (code == null||!validateCode.equals(code)) {
            throw new IllegalArgumentException("验证码不正确");
        }
    }

    private void checkPayPassword(String realPayPassword,String payPassword) {
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        System.out.println(encoder.encode(payPassword));
        boolean isMatch = encoder.matches(payPassword, realPayPassword);
        if (!isMatch) {
            throw new IllegalArgumentException("支付密码不正确");
        }
    }
}
